package net.hands.common.mail;

import java.util.Date;
import java.util.LinkedList;
import java.util.Map;

import javax.activation.DataHandler;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
/**
 * 
 * 说明:发送邮件会话
 * <br>
 * <p>这是一个开源的软件，请在LGPLv3下合法使用、修改或重新发布。</p>
 * @author 陈侃(cknet@126.com, 13910090885)
 *         http://code.google.com/p/simpleframework/
 *         http://www.simpleframework.net
 */
public class SendMailSession {
   /**
    * 选择
    */
	private static final String ALTERNATIVE = "alternative";
	/**
	 * 字符
	 */
	private static final String CHARSET = ";charset=";
	/**
	 * 内容id不为null
	 */
	private static final String INLINE = "inline";
   /**
    * 邮件会话
    */
	protected final Session mailSession;
	/**
	 * 邮件传输
	 */
	protected final Transport mailTransport;
   /**
    * 
   * Constructor Method  
   * @update 2012-9-21 下午12:29:09  
   * @param session 会话
   * @param transport 运输
    */
	public SendMailSession(final Session session, final Transport transport) {
		this.mailSession = session;
		this.mailTransport = transport;
	}
   /**
    * 说明:打开传输
    * @update 2012-9-21 下午12:29:18
    */
	public void open() {
		try {
			mailTransport.connect();
		} catch (final MessagingException msex) {
			throw new MailException("Unable to connect", msex);
		}
	}
   /**
   * 说明:发送邮件
   * @param mail 邮件
   * @update 2012-9-21 下午12:29:52
    */
	public void sendMail(final Email mail) {
		//信息
		Message msg;
		try {
			msg = createMessage(mail, mailSession);
		} catch (final MessagingException mex) {
			throw new MailException("Unable to prepare email message: " + mail, mex);
		}
		try {
			mailTransport.sendMessage(msg, msg.getAllRecipients());
		} catch (final MessagingException mex) {
			throw new MailException("Unable to send email message: " + mail, mex);
		}
	}
  /**
   * 
  * 说明：关闭
  * @update 2012-9-29 下午4:45:17
   */
	public void close() {
		try {
			mailTransport.close();
		} catch (final MessagingException mex) {
			throw new MailException("Unable to close session", mex);
		}
	}

	// ---------------------------------------------------------------- adapter
   /**
   * 说明:创建信息
   * @param email 邮件
   * @param session 会话
   * @return Message
   * @throws MessagingException
   * @update 2012-9-21 下午12:30:40
    */
	protected Message createMessage(final Email email, final Session session)
			throws MessagingException {
		//创建邮件信息
		final Message msg = new MimeMessage(session);
		//设置信息来源地址
		msg.setFrom(new InternetAddress(email.getFrom()));
         
		// 设置信息邮件发送地址
		final int totalTo = email.getTo().length;
		InternetAddress[] address = new InternetAddress[totalTo];
		for (int i = 0; i < totalTo; i++) {
			address[i] = new InternetAddress(email.getTo()[i]);
		}
		//设置信息接受者
		msg.setRecipients(Message.RecipientType.TO, address);

		// 信息回复者
		if (email.getReplyTo() != null) {
			final int totalReplyTo = email.getReplyTo().length;
			address = new InternetAddress[totalReplyTo];
			for (int i = 0; i < totalReplyTo; i++) {
				address[i] = new InternetAddress(email.getReplyTo()[i]);
			}
			msg.setReplyTo(address);
		}

		// 信息抄送者
		if (email.getCc() != null) {
			final int totalCc = email.getCc().length;
			address = new InternetAddress[totalCc];
			for (int i = 0; i < totalCc; i++) {
				address[i] = new InternetAddress(email.getCc()[i]);
			}
			msg.setRecipients(Message.RecipientType.CC, address);
		}

		// 信息被抄送者
		if (email.getBcc() != null) {
			final int totalBcc = email.getBcc().length;
			address = new InternetAddress[totalBcc];
			for (int i = 0; i < totalBcc; i++) {
				address[i] = new InternetAddress(email.getBcc()[i]);
			}
			msg.setRecipients(Message.RecipientType.BCC, address);
		}

		//设置信息主题
		msg.setSubject(email.getSubject());
		//设置发送日期
		Date date = email.getSentDate();
		if (date == null) {
			date = new Date();
		}
		msg.setSentDate(date);

		// 设置信息头
		final Map<String, String> headers = email.getAllHeaders();
		if (headers != null) {
			for (final Map.Entry<String, String> stringStringEntry : headers.entrySet()) {
				final String value = stringStringEntry.getValue();
				msg.setHeader(stringStringEntry.getKey(), value);
			}
		}

		//信息内容
		final LinkedList<EmailMessage> messages = email.getAllMessages();
		//信息附件
		final LinkedList<EmailAttachment> attachments = email.getAttachments();
	   //信息内容条数
		final int totalMessages = messages.size();
      //附件集合为空并且信息条数等于1
		if ((attachments == null) && (totalMessages == 1)) {
			final EmailMessage emailMessage = messages.get(0);//获得邮件信息
			//信息设置内容
			msg.setContent(emailMessage.getContent(), emailMessage.getMimeType() + CHARSET
					+ emailMessage.getEncoding());
		} else {
			//多块信息
			final Multipart multipart = new MimeMultipart();
			Multipart msgMultipart = multipart;
			if (totalMessages > 1) {//信息条数大于1
				final MimeBodyPart body = new MimeBodyPart();//主体块
				msgMultipart = new MimeMultipart(ALTERNATIVE);//选择块
				body.setContent(msgMultipart);
				multipart.addBodyPart(body);
			}
			for (final EmailMessage emailMessage : messages) {//遍历信息
				final MimeBodyPart messageData = new MimeBodyPart();
				messageData.setContent(emailMessage.getContent(), emailMessage.getMimeType() + CHARSET
						+ emailMessage.getEncoding());
				msgMultipart.addBodyPart(messageData);
			}
			if (attachments != null) {//遍历附件
				for (final EmailAttachment att : attachments) {
					final MimeBodyPart attBodyPart = new MimeBodyPart();
					attBodyPart.setFileName(att.getName());
					attBodyPart.setDataHandler(new DataHandler(att.getDataSource()));
					if (att.isInline()) {//内容id不为null
						attBodyPart.setContentID(att.getContentId());
						attBodyPart.setDisposition(INLINE);
					}
					multipart.addBodyPart(attBodyPart);
				}
			}
			msg.setContent(multipart);
		}
		return msg;
	}
}
